package com.engine.salary.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.engine.common.util.ServiceUtil;
import com.engine.core.impl.Service;
import com.engine.salary.entity.datacollection.DataCollectionEmployee;
import com.engine.salary.entity.siaccount.po.InsuranceAccountDetailPO;
import com.engine.salary.entity.siaccount.po.InsuranceAccountInspectPO;
import com.engine.salary.entity.siarchives.po.InsuranceArchivesAccountPO;
import com.engine.salary.entity.siarchives.po.InsuranceArchivesFundSchemePO;
import com.engine.salary.entity.siarchives.po.InsuranceArchivesOtherSchemePO;
import com.engine.salary.entity.siarchives.po.InsuranceArchivesSocialSchemePO;
import com.engine.salary.entity.taxagent.po.TaxAgentPO;
import com.engine.salary.enums.UserStatusEnum;
import com.engine.salary.enums.siaccount.BillStatusEnum;
import com.engine.salary.enums.siaccount.ResourceFromEnum;
import com.engine.salary.enums.sicategory.PaymentScopeEnum;
import com.engine.salary.mapper.datacollection.EmployMapper;
import com.engine.salary.mapper.sischeme.InsuranceSchemeMapper;
import com.engine.salary.mapper.taxagent.TaxAgentMapper;
import com.engine.salary.service.RecordsBuildService;
import com.engine.salary.service.SIArchivesService;
import com.engine.salary.service.SalaryEmployeeService;
import com.engine.salary.util.SalaryAssert;
import com.engine.salary.util.SalaryDateUtil;
import com.engine.salary.util.SalaryEnumUtil;
import com.engine.salary.util.SalaryI18nUtil;
import com.engine.salary.util.db.MapperProxyFactory;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import weaver.general.Util;
import weaver.hrm.User;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Author weaver_cl
 * @Description:
 * @Date 2022/4/11
 * @Version V1.0
 **/
public class RecordsBuildServiceImpl extends Service implements RecordsBuildService {

    private EmployMapper getEmployMapper() {
        return MapperProxyFactory.getProxy(EmployMapper.class);
    }

    private TaxAgentMapper getTaxAgentMapper() {
        return MapperProxyFactory.getProxy(TaxAgentMapper.class);
    }

    private InsuranceSchemeMapper getInsuranceSchemeMapper() {
        return MapperProxyFactory.getProxy(InsuranceSchemeMapper.class);
    }

    private SalaryEmployeeService getSalaryEmployeeService(User user) {
        return ServiceUtil.getService(SalaryEmployeeServiceImpl.class, user);
    }

//    private SIArchivesBiz siArchivesBiz = new SIArchivesBiz();

    public SIArchivesService getSIArchivesService(User user) {
        return ServiceUtil.getService(SIArchivesServiceImpl.class, user);
    }

    @Override
    public List<Map<String, Object>> buildCommonRecords(List<InsuranceAccountDetailPO> list, Long employeeId, boolean dynamicEmpInfo) {
//        boolean welBaseDiffSign = siArchivesBiz.isDiffWelBase();
        boolean welBaseDiffSign = getSIArchivesService(user).isDiffWelBase();
        List<Map<String, Object>> result = new ArrayList<>();
        if (CollectionUtils.isEmpty(list)) {
            return result;
        }
        List<Long> employeeIds = list.stream().map(item -> item.getEmployeeId()).distinct().collect(Collectors.toList());
        List<DataCollectionEmployee> employeeByIds = new ArrayList<>();
        List<List<Long>> partition = Lists.partition(employeeIds, 1000);
        for (List<Long> longs : partition) {
            employeeByIds.addAll(getSalaryEmployeeService(user).getEmployeeByIdsAll(longs));
        }
        if (CollectionUtils.isEmpty(employeeByIds)) {
            return result;
        }
        List<TaxAgentPO> paymentList = getTaxAgentMapper().listAll();

        SalaryAssert.notEmpty(paymentList, SalaryI18nUtil.getI18nLabel(100341, "暂无扣缴义务人"));
        Map<Long, TaxAgentPO> paymentMap = paymentList.stream().collect(Collectors.toMap(TaxAgentPO::getId, Function.identity()));
        Map<Long, DataCollectionEmployee> collect = employeeByIds.stream().collect(Collectors.toMap(DataCollectionEmployee::getEmployeeId, Function.identity()));
        list.forEach(item -> {
            Map<String, Object> record = new HashMap<>();
            DataCollectionEmployee simpleEmployee = collect.get(item.getEmployeeId());
            record.put("id", item.getId());
            record.put("employeeId", item.getEmployeeId());
            record.put("billMonth", item.getBillMonth());
            record.put("billStatus", SalaryEnumUtil.enumMatchByValue(item.getBillStatus(), BillStatusEnum.values(), BillStatusEnum.class));
            record.put("userName", simpleEmployee.getUsername());
            record.put("mobile", simpleEmployee.getMobile());
            if (!dynamicEmpInfo) {
                record.put("department", item.getDepartmentName());
                record.put("departmentId", item.getDepartmentId());
                record.put("subcompany", item.getSubcompanyName());
                record.put("subcompanyId", item.getSubcompanyId());
                record.put("jobtitle", item.getJobtitleName());
                record.put("jobtitleId", item.getJobtitleId());
                record.put("jobcall", item.getJobcall());
                record.put("jobcallId", item.getJobcallId());
                record.put("employeeStatus", item.getStatus() != null ? UserStatusEnum.getDefaultLabelByValue(Integer.parseInt(item.getStatus())) : "");
            } else {
                record.put("department", simpleEmployee.getDepartmentName());
                record.put("departmentId", simpleEmployee.getDepartmentId());
                record.put("employeeStatus", simpleEmployee.getStatus() != null ? UserStatusEnum.getDefaultLabelByValue(Integer.parseInt(simpleEmployee.getStatus())) : "");
            }

            record.put("supplementaryMonth", item.getSupplementaryMonth());
            ResourceFromEnum from = SalaryEnumUtil.enumMatchByValue(item.getResourceFrom(), ResourceFromEnum.values(), ResourceFromEnum.class);
            record.put("workcode", StringUtils.isBlank(simpleEmployee.getWorkcode()) ? "" : simpleEmployee.getWorkcode());
            record.put("idNo", Util.null2String(simpleEmployee.getIdNo()));
            record.put("sourceFrom", SalaryI18nUtil.getI18nLabel(from.getLabelId(), from.getDefaultLabel()));
            record.put("socialPayOrg", paymentMap.get(item.getSocialPayOrg()) == null ? "" : paymentMap.get(item.getSocialPayOrg()).getName());
            record.put("socialAccount", item.getSocialAccount());

            record.put("socialSchemeName", getInsuranceSchemeMapper().querySchemeName(item.getSocialSchemeId()));
            if (StringUtils.isNotEmpty(item.getSocialPaymentBaseString()) || StringUtils.isNotEmpty(item.getSocialPaymentComBaseString())) {
                Map<String, Object> socialJson = JSON.parseObject(item.getSocialPaymentBaseString(), new HashMap<String, Object>().getClass());
//                if(socialJson!=null){
//                    socialJson.forEach((k, v) -> {
//                        record.put(k + "socialBase", (String) v);
//                    });
//                }
                if (welBaseDiffSign) {
                    if (socialJson != null) {
                        //查询该福利方案下开启缴纳的福利项
//                        List<Long> insuranceIdList = siArchivesBiz.payInsuranceIds(item.getSocialSchemeId(), PaymentScopeEnum.SCOPE_PERSON.getValue());
                        List<Long> insuranceIdList = getSIArchivesService(user).payInsuranceIds(item.getSocialSchemeId(), PaymentScopeEnum.SCOPE_PERSON.getValue());
                        socialJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                record.put(k + "socialPerBase", v);
                            }
                        });
                    }
                    Map<String, Object> socialComJson = JSON.parseObject(item.getSocialPaymentComBaseString(), new TypeReference<Map<String, Object>>() {
                    });
                    if (socialComJson != null) {
                        //查询该福利方案下开启缴纳的福利项
//                        List<Long> insuranceIdList = siArchivesBiz.payInsuranceIds(item.getSocialSchemeId(),PaymentScopeEnum.SCOPE_COMPANY.getValue());
                        List<Long> insuranceIdList = getSIArchivesService(user).payInsuranceIds(item.getSocialSchemeId(),PaymentScopeEnum.SCOPE_COMPANY.getValue());
                        socialComJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                record.put(k + "socialComBase", v);
                            }
                        });
                    }
                } else {
                    if (socialJson != null) {
                        //查询该福利方案下开启缴纳的福利项
//                        List<Long> insuranceIdList = siArchivesBiz.payInsuranceIds(item.getSocialSchemeId());
                        List<Long> insuranceIdList = getSIArchivesService(user).payInsuranceIds(item.getSocialSchemeId());
                        socialJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                record.put(k + "socialBase", v);
                            }
                        });
                    }
                }
            }
            record.put("fundPayOrg", item.getFundPayOrg() == null ? "" : (paymentMap.getOrDefault(item.getFundPayOrg(),TaxAgentPO.builder().build())).getName());
            record.put("fundAccount", item.getFundAccount());
            record.put("fundSchemeName", getInsuranceSchemeMapper().querySchemeName(item.getFundSchemeId()));
            record.put("supplementFundAccount", item.getSupplementFundAccount());
            if (StringUtils.isNotEmpty(item.getFundPaymentBaseString()) || StringUtils.isNotEmpty(item.getFundPaymentComBaseString())) {
                Map<String, Object> fundJson = JSON.parseObject(item.getFundPaymentBaseString(), new HashMap<String, Object>().getClass());
//                if(fundJson!=null){
//                    fundJson.forEach((k, v) -> {
//                        record.put(k + "fundBase", (String) v);
//                    });
//                }
                if (welBaseDiffSign) {
                    if (fundJson != null) {
                        //查询该福利方案下开启缴纳的福利项
//                        List<Long> insuranceIdList = siArchivesBiz.payInsuranceIds(item.getFundSchemeId(),PaymentScopeEnum.SCOPE_PERSON.getValue());
                        List<Long> insuranceIdList = getSIArchivesService(user).payInsuranceIds(item.getFundSchemeId(),PaymentScopeEnum.SCOPE_PERSON.getValue());
                        fundJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                record.put(k + "fundPerBase", v);
                            }
                        });
                    }
                    Map<String, Object> fundComJson = JSON.parseObject(item.getFundPaymentComBaseString(), new TypeReference<Map<String, Object>>() {
                    });
                    if (fundComJson != null) {
                        //查询该福利方案下开启缴纳的福利项
//                        List<Long> insuranceIdList = siArchivesBiz.payInsuranceIds(item.getFundSchemeId(),PaymentScopeEnum.SCOPE_COMPANY.getValue());
                        List<Long> insuranceIdList = getSIArchivesService(user).payInsuranceIds(item.getFundSchemeId(),PaymentScopeEnum.SCOPE_COMPANY.getValue());
                        fundComJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                record.put(k + "fundComBase", v);
                            }
                        });
                    }
                } else {
                    if (fundJson != null) {
                        //查询该福利方案下开启缴纳的福利项
//                        List<Long> insuranceIdList = siArchivesBiz.payInsuranceIds(item.getFundSchemeId());
                        List<Long> insuranceIdList = getSIArchivesService(user).payInsuranceIds(item.getFundSchemeId());
                        fundJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                record.put(k + "fundBase", v);
                            }
                        });
                    }
                }
            }
            record.put("otherPayOrg", item.getOtherPayOrg() == null ? "" : (paymentMap.getOrDefault(item.getOtherPayOrg(),TaxAgentPO.builder().build())).getName());
            record.put("otherSchemeName", getInsuranceSchemeMapper().querySchemeName(item.getOtherSchemeId()));
            if (StringUtils.isNotEmpty(item.getOtherPaymentBaseString()) || StringUtils.isNotEmpty(item.getOtherPaymentComBaseString())) {
                Map<String, Object> otherJson = JSON.parseObject(item.getOtherPaymentBaseString(), new HashMap<String, Object>().getClass());
//                if(otherJson!=null){
//                    otherJson.forEach((k, v) -> {
//                        record.put(k + "otherBase", (String) v);
//                    });
//                }
                if (welBaseDiffSign) {
                    if (otherJson != null) {
                        //查询该福利方案下开启缴纳的福利项
//                        List<Long> insuranceIdList = siArchivesBiz.payInsuranceIds(item.getOtherSchemeId(),PaymentScopeEnum.SCOPE_PERSON.getValue());
                        List<Long> insuranceIdList = getSIArchivesService(user).payInsuranceIds(item.getOtherSchemeId(),PaymentScopeEnum.SCOPE_PERSON.getValue());
                        otherJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                record.put(k + "otherPerBase", v);
                            }
                        });
                    }
                    Map<String, Object> otherComJson = JSON.parseObject(item.getOtherPaymentComBaseString(), new TypeReference<Map<String, Object>>() {
                    });
                    if (otherComJson != null) {
                        //查询该福利方案下开启缴纳的福利项
//                        List<Long> insuranceIdList = siArchivesBiz.payInsuranceIds(item.getOtherSchemeId(),PaymentScopeEnum.SCOPE_COMPANY.getValue());
                        List<Long> insuranceIdList = getSIArchivesService(user).payInsuranceIds(item.getOtherSchemeId(),PaymentScopeEnum.SCOPE_COMPANY.getValue());
                        otherComJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                record.put(k + "otherComBase", v);
                            }
                        });
                    }
                } else {
                    if (otherJson != null) {
                        //查询该福利方案下开启缴纳的福利项
//                        List<Long> insuranceIdList = siArchivesBiz.payInsuranceIds(item.getOtherSchemeId());
                        List<Long> insuranceIdList = getSIArchivesService(user).payInsuranceIds(item.getOtherSchemeId());
                        otherJson.forEach((k, v) -> {
                            if (insuranceIdList.contains(Long.valueOf(k))) {
                                record.put(k + "otherBase", v);
                            }
                        });
                    }
                }
            }
            if (StringUtils.isNotEmpty(item.getSocialPerJson())) {
                Map<String, Object> socialJson = JSON.parseObject(item.getSocialPerJson(), new HashMap<String, Object>().getClass());
                if(socialJson!=null){
                    socialJson.forEach((k, v) -> {
                        record.put(k + "socialPer", (String) v);
                    });
                }

            }
            record.put("socialPerSum", item.getSocialPerSum());
            if (StringUtils.isNotEmpty(item.getFundPerJson())) {
                Map<String, Object> fundPerJson = JSON.parseObject(item.getFundPerJson(), new HashMap<String, Object>().getClass());
                if(fundPerJson!=null){
                    fundPerJson.forEach((k, v) -> {
                        record.put(k + "fundPer", (String) v);
                    });
                }

            }
            record.put("fundPerSum", item.getFundPerSum());
            if (StringUtils.isNotEmpty(item.getOtherPerJson())) {
                Map<String, Object> fundPerJson = JSON.parseObject(item.getOtherPerJson(), new HashMap<String, Object>().getClass());
                if(fundPerJson!=null){
                    fundPerJson.forEach((k, v) -> {
                        record.put(k + "otherPer", (String) v);
                    });
                }

            }
            record.put("otherPerSum", item.getOtherPerSum());
            record.put("perSum", item.getPerSum());
            if (StringUtils.isNotEmpty(item.getSocialComJson())) {
                Map<String, Object> fundPerJson = JSON.parseObject(item.getSocialComJson(), new HashMap<String, Object>().getClass());
                if(fundPerJson!=null){
                    fundPerJson.forEach((k, v) -> {
                        record.put(k + "socialCom", (String) v);
                    });
                }
                fundPerJson.forEach((k, v) -> {
                    record.put(k + "socialCom", (String) v);
                });
            }
            record.put("socialComSum", item.getSocialComSum());
            if (StringUtils.isNotEmpty(item.getFundComJson())) {
                Map<String, Object> fundPerJson = JSON.parseObject(item.getFundComJson(), new HashMap<String, Object>().getClass());
                if(fundPerJson!=null){
                    fundPerJson.forEach((k, v) -> {
                        record.put(k + "fundCom", (String) v);
                    });
                }

            }
            record.put("fundComSum", item.getFundComSum());
            if (StringUtils.isNotEmpty(item.getOtherComJson())) {
                Map<String, Object> fundPerJson = JSON.parseObject(item.getOtherComJson(), new HashMap<String, Object>().getClass());
                if(fundPerJson!=null){
                    fundPerJson.forEach((k, v) -> {
                        record.put(k + "otherCom", (String) v);
                    });
                }

            }
            record.put("otherComSum", item.getOtherComSum());
            record.put("comSum", item.getComSum());
            record.put("socialSum", item.getSocialSum());
            record.put("fundSum", item.getFundSum());
            record.put("otherSum", item.getOtherSum());
            record.put("total", item.getTotal());
            result.add(record);
        });
        return result;
    }

    @Override
    public List<Map<String, Object>> buildCommonRecordsWithStyle(List<InsuranceAccountDetailPO> list, Long employeeId) {
        return null;
    }

    @Override
    public List<Map<String, Object>> buildInspectRecords(List<InsuranceAccountInspectPO> list, Long paymentOrganization) {
        List<Map<String, Object>> result = new ArrayList<>();

        if (CollectionUtils.isEmpty(list)) {
            return result;
        }
        List<Long> employeeIds = list.stream().map(InsuranceAccountInspectPO::getEmployeeId).collect(Collectors.toList());
        List<DataCollectionEmployee> employeeByIds = new ArrayList<>();
        List<List<Long>> partition = Lists.partition(employeeIds, 1000);
        for (List<Long> longs : partition) {
            employeeByIds.addAll(getSalaryEmployeeService(user).getEmployeeByIdsAll(longs));
        }
        if (CollectionUtils.isEmpty(employeeByIds)) {
            return result;
        }
        Map<Long, DataCollectionEmployee> collect = employeeByIds.stream().collect(Collectors.toMap(DataCollectionEmployee::getEmployeeId, Function.identity()));
//        Map<Long, InsuranceArchivesAccountPO> insuranceArchivesAccountPOMap = siArchivesBiz.buildBatchAccount(employeeIds, paymentOrganization);
        Map<Long, InsuranceArchivesAccountPO> insuranceArchivesAccountPOMap = getSIArchivesService(user).buildBatchAccount(employeeIds, paymentOrganization);
        list.forEach(item -> {
            Map<String, Object> record = new HashMap<>();
            DataCollectionEmployee simpleEmployee = collect.get(item.getEmployeeId()) == null ? new DataCollectionEmployee() : collect.get(item.getEmployeeId());
            InsuranceArchivesAccountPO insuranceAccountInspectPO = insuranceArchivesAccountPOMap.get(item.getEmployeeId());
            record.put("id", item.getId());
            record.put("employeeId", item.getEmployeeId());
            record.put("billMonth", item.getBillMonth());
            record.put("userName", simpleEmployee.getUsername());
            record.put("inspectStatus", item.getInspectStatus());
            record.put("department", simpleEmployee.getDepartmentName());
            record.put("supplementaryMonth", timeFormat(item.getSupplementaryMonth()));
            record.put("mobile", simpleEmployee.getMobile());
            record.put("employeeStatus", simpleEmployee.getStatus());
            InsuranceArchivesSocialSchemePO social = insuranceAccountInspectPO.getSocial();
            if (social != null) {
                record.put("socialSchemeName", getInsuranceSchemeMapper().querySchemeName(social.getSocialSchemeId()));
                if (StringUtils.isNotEmpty(social.getSocialPaymentBaseString())) {
                    Map<String, Object> socialJson = JSON.parseObject(social.getSocialPaymentBaseString(), new HashMap<String, Object>().getClass());
                    socialJson.forEach((k, v) -> {
                        record.put(k + "socialBase", (String) v);
                    });
                }
            }
            InsuranceArchivesFundSchemePO fund = insuranceAccountInspectPO.getFund();
            if (fund != null) {
                record.put("fundSchemeName", getInsuranceSchemeMapper().querySchemeName(fund.getFundSchemeId()));
                if (StringUtils.isNotEmpty(fund.getFundPaymentBaseString())) {
                    Map<String, Object> socialJson = JSON.parseObject(fund.getFundPaymentBaseString(), new HashMap<String, Object>().getClass());
                    socialJson.forEach((k, v) -> {
                        record.put(k + "fundBase", (String) v);
                    });
                }
            }
            InsuranceArchivesOtherSchemePO other = insuranceAccountInspectPO.getOther();
            if (other != null) {
                record.put("otherSchemeName", getInsuranceSchemeMapper().querySchemeName(other.getOtherSchemeId()));
                if (StringUtils.isNotEmpty(other.getOtherPaymentBaseString())) {
                    Map<String, Object> socialJson = JSON.parseObject(other.getOtherPaymentBaseString(), new HashMap<String, Object>().getClass());
                    socialJson.forEach((k, v) -> {
                        record.put(k + "otherBase", (String) v);
                    });
                }
            }
            result.add(record);
        });
        return result;
    }


    public String timeFormat(String originTime) {
        if (StringUtils.isBlank(originTime) || !SalaryDateUtil.checkYearMonth(originTime)) {
            return null;
        }
        Date date = null;
        try {
            date = new SimpleDateFormat("yyyy-MM").parse(originTime);
        } catch (ParseException e) {
            //log.error("time format error", e);
        }
        return new SimpleDateFormat(SalaryI18nUtil.getI18nLabel(100519, "补缴yyyy年MM月")).format(date);
    }
}